/**
 * MCP 协议核心实现
 *
 * 完全符合 Model Context Protocol 规范
 * 不依赖任何特定 SDK 实现
 *
 * @see https://spec.modelcontextprotocol.io/
 */

import type { JsonSchema } from './json-schema-adapter.js';
import { JsonSchemaAdapter } from './json-schema-adapter.js';
import { JsonSchemaValidator } from './json-validator.js';
import type { ToolDefinition } from './tool-schema.js';

// ============================================================================
// JSON-RPC 2.0 类型定义
// ============================================================================

export interface JsonRpcRequest {
  jsonrpc: '2.0';
  method: string;
  params?: any;
  id: string | number | null;
}

export interface JsonRpcResponse {
  jsonrpc: '2.0';
  result?: any;
  error?: JsonRpcError;
  id: string | number | null;
}

export interface JsonRpcError {
  code: number;
  message: string;
  data?: any;
}

// JSON-RPC 2.0 错误码
export const JsonRpcErrorCode = {
  PARSE_ERROR: -32700,
  INVALID_REQUEST: -32600,
  METHOD_NOT_FOUND: -32601,
  INVALID_PARAMS: -32602,
  INTERNAL_ERROR: -32603,
  // MCP 特定错误码
  RESOURCE_NOT_FOUND: -32001,
  RESOURCE_ALREADY_EXISTS: -32002,
  PERMISSION_DENIED: -32003,
} as const;

// ============================================================================
// MCP 协议类型定义
// ============================================================================

export interface MCPServerInfo {
  name: string;
  version: string;
  protocolVersion?: string;
  capabilities?: MCPServerCapabilities;
}

export interface MCPServerCapabilities {
  tools?: {
    listChanged?: boolean;
  };
  resources?: {
    listChanged?: boolean;
    subscribe?: boolean;
  };
  prompts?: {
    listChanged?: boolean;
  };
  logging?: {};
}

export interface MCPClientInfo {
  name: string;
  version: string;
}

export interface MCPClientCapabilities {
  experimental?: Record<string, any>;
  sampling?: Record<string, any>;
  tools?: {
    hallucination?: boolean;
  };
}

// Initialize 请求/响应
export interface InitializeRequest {
  jsonrpc: '2.0';
  method: 'initialize';
  params: {
    protocolVersion: string;
    capabilities: MCPClientCapabilities;
    clientInfo: MCPClientInfo;
  };
  id: string | number;
}

export interface InitializeResponse {
  jsonrpc: '2.0';
  result: {
    protocolVersion: string;
    capabilities: MCPServerCapabilities;
    serverInfo: MCPServerInfo;
  };
  id: string | number;
}

// Tools 相关类型
export interface ToolDescription {
  name: string;
  description?: string;
  inputSchema?: JsonSchema;
}

export interface ListToolsRequest {
  jsonrpc: '2.0';
  method: 'tools/list';
  params?: {
    cursor?: string;
  };
  id: string | number;
}

export interface ListToolsResponse {
  jsonrpc: '2.0';
  result: {
    tools: ToolDescription[];
    nextCursor?: string;
  };
  id: string | number;
}

export interface CallToolRequest {
  jsonrpc: '2.0';
  method: 'tools/call';
  params: {
    name: string;
    arguments?: any;
  };
  id: string | number;
}

export interface CallToolResponse {
  jsonrpc: '2.0';
  result: {
    content: Array<{
      type: 'text' | 'image' | 'resource';
      text?: string;
      data?: string;
      mimeType?: string;
      uri?: string;
    }>;
    isError?: boolean;
  };
  id: string | number;
}

// ============================================================================
// MCP 协议处理器
// ============================================================================

export class MCPProtocolHandler {
  private serverInfo: MCPServerInfo;
  private tools: Map<string, ToolDefinition> = new Map();
  private validator: JsonSchemaValidator;
  private initialized: boolean = false;
  private clientCapabilities?: MCPClientCapabilities;

  constructor(serverInfo: MCPServerInfo) {
    this.serverInfo = {
      ...serverInfo,
      protocolVersion: '2024-11-05', // MCP 协议版本
      capabilities: {
        tools: {
          listChanged: true,
        },
        ...serverInfo.capabilities,
      },
    };
    this.validator = new JsonSchemaValidator();
  }

  /**
   * 注册工具
   */
  registerTool(tool: ToolDefinition): void {
    this.tools.set(tool.meta.name, tool);
  }

  /**
   * 注销工具
   */
  unregisterTool(name: string): boolean {
    return this.tools.delete(name);
  }

  /**
   * 获取所有工具
   */
  getTools(): ToolDefinition[] {
    return Array.from(this.tools.values());
  }

  /**
   * 处理 JSON-RPC 请求
   */
  async handleRequest(request: JsonRpcRequest): Promise<JsonRpcResponse> {
    try {
      // 验证 JSON-RPC 格式
      if (request.jsonrpc !== '2.0') {
        return this.createErrorResponse(
          request.id,
          JsonRpcErrorCode.INVALID_REQUEST,
          'Invalid JSON-RPC version'
        );
      }

      // 路由到相应的处理方法
      switch (request.method) {
        case 'initialize':
          return this.handleInitialize(request as InitializeRequest);

        case 'initialized':
          return this.handleInitialized(request);

        case 'tools/list':
          return this.handleListTools(request as ListToolsRequest);

        case 'tools/call':
          return this.handleCallTool(request as CallToolRequest);

        case 'notifications/capabilities/changed':
          return this.handleCapabilitiesChanged(request);

        case 'ping':
          return this.handlePing(request);

        default:
          return this.createErrorResponse(
            request.id,
            JsonRpcErrorCode.METHOD_NOT_FOUND,
            `Method '${request.method}' not found`
          );
      }
    } catch (error) {
      return this.createErrorResponse(
        request.id,
        JsonRpcErrorCode.INTERNAL_ERROR,
        error instanceof Error ? error.message : 'Internal error'
      );
    }
  }

  /**
   * 处理 initialize 请求
   */
  private async handleInitialize(request: InitializeRequest): Promise<InitializeResponse> {
    // 验证协议版本参数
    if (!request.params?.protocolVersion) {
      return this.createErrorResponse(
        request.id,
        JsonRpcErrorCode.INVALID_PARAMS,
        'protocolVersion is required'
      ) as InitializeResponse;
    }

    // 验证协议版本兼容性
    const requestedVersion = request.params.protocolVersion;
    const supportedVersion = this.serverInfo.protocolVersion || '2024-11-05';

    // 简单的版本兼容性检查
    const isCompatible = this.checkProtocolCompatibility(requestedVersion, supportedVersion);

    if (!isCompatible) {
      console.warn(
        `Protocol version mismatch: client=${requestedVersion}, server=${supportedVersion}`
      );
    }

    // 存储客户端能力
    this.clientCapabilities = request.params.capabilities;
    this.initialized = true;

    return {
      jsonrpc: '2.0',
      result: {
        protocolVersion: supportedVersion,
        capabilities: this.serverInfo.capabilities || {},
        serverInfo: {
          name: this.serverInfo.name,
          version: this.serverInfo.version,
        },
      },
      id: request.id,
    };
  }

  /**
   * 处理 initialized 通知
   */
  private async handleInitialized(request: JsonRpcRequest): Promise<JsonRpcResponse> {
    // initialized 是一个通知，不返回响应
    if (request.id !== null && request.id !== undefined) {
      return this.createErrorResponse(
        request.id,
        JsonRpcErrorCode.INVALID_REQUEST,
        'initialized is a notification and should not have an id'
      );
    }

    // 不返回响应
    return { jsonrpc: '2.0', id: null };
  }

  /**
   * 处理 tools/list 请求
   */
  private async handleListTools(request: ListToolsRequest): Promise<ListToolsResponse> {
    // 检查是否已初始化
    if (!this.initialized) {
      return this.createErrorResponse(
        request.id,
        JsonRpcErrorCode.RESOURCE_NOT_FOUND,
        'Server not initialized'
      ) as ListToolsResponse;
    }

    const tools = this.getTools();
    const toolDescriptions: ToolDescription[] = tools.map(tool => ({
      name: tool.meta.name,
      description: tool.meta.description,
      inputSchema: JsonSchemaAdapter.toolMetaToJsonSchema(tool.meta),
    }));

    // TODO: 实现分页支持
    const cursor = request.params?.cursor;
    if (cursor) {
      // 分页逻辑
    }

    return {
      jsonrpc: '2.0',
      result: {
        tools: toolDescriptions,
      },
      id: request.id,
    };
  }

  /**
   * 处理 tools/call 请求
   */
  private async handleCallTool(request: CallToolRequest): Promise<CallToolResponse> {
    // 检查是否已初始化
    if (!this.initialized) {
      return this.createErrorResponse(
        request.id,
        JsonRpcErrorCode.RESOURCE_NOT_FOUND,
        'Server not initialized'
      ) as CallToolResponse;
    }

    const { name, arguments: args = {} } = request.params;

    // 查找工具
    const tool = this.tools.get(name);
    if (!tool) {
      return this.createErrorResponse(
        request.id,
        JsonRpcErrorCode.METHOD_NOT_FOUND,
        `Tool '${name}' not found`
      ) as CallToolResponse;
    }

    try {
      // 验证参数
      if (tool.meta.parameters && Object.keys(tool.meta.parameters).length > 0) {
        const schema = JsonSchemaAdapter.toolMetaToJsonSchema(tool.meta);
        const validationResult = this.validator.validate(args, schema);

        if (!validationResult.valid) {
          return {
            jsonrpc: '2.0',
            result: {
              content: [
                {
                  type: 'text',
                  text: JSON.stringify({
                    error: 'Invalid parameters',
                    details: validationResult.errors,
                  }),
                },
              ],
              isError: true,
            },
            id: request.id,
          };
        }
      }

      // 执行工具
      const result = await tool.handler(args);

      // 格式化响应
      let content: CallToolResponse['result']['content'];

      if (typeof result === 'string') {
        content = [{ type: 'text', text: result }];
      } else if (typeof result === 'object') {
        content = [
          {
            type: 'text',
            text: JSON.stringify(result),
          },
        ];
      } else {
        content = [
          {
            type: 'text',
            text: String(result),
          },
        ];
      }

      return {
        jsonrpc: '2.0',
        result: {
          content,
          isError: false,
        },
        id: request.id,
      };
    } catch (error) {
      // 错误处理
      return {
        jsonrpc: '2.0',
        result: {
          content: [
            {
              type: 'text',
              text: JSON.stringify({
                error: error instanceof Error ? error.message : 'Unknown error',
                stack: error instanceof Error ? error.stack : undefined,
              }),
            },
          ],
          isError: true,
        },
        id: request.id,
      };
    }
  }

  /**
   * 处理能力变更通知
   */
  private async handleCapabilitiesChanged(request: JsonRpcRequest): Promise<JsonRpcResponse> {
    // 这是一个通知，不需要响应
    if (request.id !== null && request.id !== undefined) {
      return this.createErrorResponse(
        request.id,
        JsonRpcErrorCode.INVALID_REQUEST,
        'Notifications should not have an id'
      );
    }

    return { jsonrpc: '2.0', id: null };
  }

  /**
   * 处理 ping 请求
   */
  private async handlePing(request: JsonRpcRequest): Promise<JsonRpcResponse> {
    return {
      jsonrpc: '2.0',
      result: { pong: true },
      id: request.id,
    };
  }

  /**
   * 创建错误响应
   */
  private createErrorResponse(
    id: string | number | null,
    code: number,
    message: string,
    data?: any
  ): JsonRpcResponse {
    return {
      jsonrpc: '2.0',
      error: {
        code,
        message,
        data,
      },
      id,
    };
  }

  /**
   * 检查协议版本兼容性
   */
  private checkProtocolCompatibility(clientVersion: string, serverVersion: string): boolean {
    // 简单实现：检查主版本号
    const clientMajor = clientVersion.split('-')[0];
    const serverMajor = serverVersion.split('-')[0];
    return clientMajor === serverMajor;
  }

  /**
   * 发送通知给客户端
   */
  sendNotification(method: string, params?: any): JsonRpcRequest {
    return {
      jsonrpc: '2.0',
      method,
      params,
      id: null, // 通知没有 id
    };
  }

  /**
   * 发送工具列表变更通知
   */
  sendToolListChangedNotification(): JsonRpcRequest {
    return this.sendNotification('notifications/tools/list_changed');
  }
}
